#pragma once
#ifndef _SERVER_PROXY_MNG_H_
#define _SERVER_PROXY_MNG_H_
#include <functional>
#include "ServerDefines.h"
#include "common/singleton.h"

using namespace std::tr1;
using namespace std::tr1::placeholders;

class CServerProxy;
struct CServerProxyFactory
{
private:
	typedef function< CServerProxy*() > ServerProxyCreator;
	typedef std::map< enServerDefine, ServerProxyCreator >	CreatorMap;

	CreatorMap mCreatorMap;
private:
	CServerProxyFactory(){}
	~CServerProxyFactory(){}

	friend struct CreateUsingNew< CServerProxyFactory >;

public:
	// regist create function.
	void RegistCreator( enServerDefine kind, ServerProxyCreator creator )
	{
		mCreatorMap[kind] = creator;
	}

	CServerProxy* Create( enServerDefine kind )
	{
		auto Pos = mCreatorMap.find( kind );
		if( Pos == mCreatorMap.end() )
			return xgc_nullptr;
		else
			return Pos->second();
	}
};
typedef SingletonHolder< CServerProxyFactory, CreateUsingNew > ServerProxyFactory;

// use template and struct construction to auto regist creator function.
template< typename t >
struct ServerProxyRegister
{
	ServerProxyRegister( enServerDefine eServerKind )
	{
		ServerProxyFactory::Instance().RegistCreator( eServerKind, &ServerProxyRegister::CreatorFunc );
	}

	static CServerProxy* CreatorFunc()
	{
		return new t();
	}
};

#define PROXY_REGIST_HELPER( PROXY, ETYPE )	static ServerProxyRegister< PROXY > PROXY##_REGISTER_##ETYPE( ETYPE )

class CServerProxyMng
{
private:
	CServerProxyMng(void);
	~CServerProxyMng(void);

	friend struct CreateUsingNew< CServerProxyMng >;
public:
	//////////////////////////////////////////////////////////////////////////
	// add server proxy link
	// center server provided uuid, so we are only provided center server uuid. common it is zero.
	CServerProxy* AddServerProxy( enServerDefine kind, s_uuid uuid, xgc_lpcstr address, xgc_uint16 port, xgc_lpvoid userdata = 0, xgc_bool connect = true, xgc_uint16 invent = 0, xgc_uint16 timeout = 0 );

	// create a proxy if proxy doesn't exist. else return the exist.
	CServerProxy* GetServerProxy( enServerDefine eServerKind );

	// find server proxy 
	CServerProxy* FindServerProxy( enServerDefine eServerKink );

private:
	mutable section mGuard;
	typedef std::map< enServerDefine, CServerProxy* >	ServerMap;
	ServerMap mServerMap;
};
typedef SingletonHolder< CServerProxyMng, CreateUsingNew > ServerProxyMng;

#endif // _SERVER_PROXY_MNG_H_